package com.dlc.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dlc.shop.allinpay.service.AllinpayCompanyService;
import com.dlc.shop.bean.dto.allinpay.AllinpayShopBankCardDTO;
import com.dlc.shop.bean.enums.AuditStatus;
import com.dlc.shop.bean.model.ShopAuditing;
import com.dlc.shop.bean.model.ShopBankCard;
import com.dlc.shop.bean.model.ShopCompany;
import com.dlc.shop.bean.model.ShopDetail;
import com.dlc.shop.bean.vo.ShopCompanyVO;
import com.dlc.shop.common.allinpay.constant.AllinpayConstant;
import com.dlc.shop.common.allinpay.constant.IdCardCollectProcessStatus;
import com.dlc.shop.common.allinpay.constant.PicType;
import com.dlc.shop.common.allinpay.member.resp.IdCardCollectByFileUploadResp;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.util.BeanUtil;
import com.dlc.shop.config.ShopConfig;
import com.dlc.shop.dao.ShopAuditingMapper;
import com.dlc.shop.dao.ShopCompanyMapper;
import com.dlc.shop.dao.ShopDetailMapper;
import com.dlc.shop.service.*;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Author lth
 * @Date 2021/8/3 16:16
 */
@Service
@AllArgsConstructor
public class ShopCompanyServiceImpl extends ServiceImpl<ShopCompanyMapper, ShopCompany> implements ShopCompanyService {
    private static final Logger logger = LoggerFactory.getLogger(ShopBankCardServiceImpl.class);

    private final ShopCompanyMapper shopCompanyMapper;
    private final ShopAuditingMapper shopAuditingMapper;
    private final ShopBankCardService shopBankCardService;
    private final ShopAuditingService shopAuditingService;
    private final ShopDetailService shopDetailService;
    private final AttachFileService attachFileService;
    private final ShopConfig shopConfig;
    private final AllinpayCompanyService allinpayCompanyService;
    private final ShopDetailMapper shopDetailMapper;
    private static final String HTTP = "http";
    private static final Integer ID_CARD_FAIL_RESULT = 2;

    @Override
    public ShopCompanyVO getInfo(Long shopId, Integer status) {
        return shopCompanyMapper.getShopCompanyByShopIdAndStatus(shopId, status);
    }

    @Override
    public void saveInfo(ShopCompany shopCompany) {
        this.checkInfo(shopCompany);
        shopCompany.setCreateTime(new Date());
        shopCompany.setUpdateTime(new Date());
        save(shopCompany);
    }

    @Override
    public void updateByShopId(ShopCompany shopCompany) {
        this.checkInfo(shopCompany);
        shopCompany.setUpdateTime(new Date());
        saveOrUpdate(shopCompany, Wrappers.lambdaUpdate(ShopCompany.class).eq(ShopCompany::getShopId, shopCompany.getShopId()).eq(ShopCompany::getStatus, shopCompany.getStatus()));
        if (shopCompany.getEndTime() == null) {
            update(shopCompany, Wrappers.lambdaUpdate(ShopCompany.class).set(ShopCompany::getEndTime, null).eq(ShopCompany::getShopId, shopCompany.getShopId()).eq(ShopCompany::getStatus, shopCompany.getStatus()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void platformUpdateShopCompany(ShopCompany shopCompany, Long shopId) {
        this.checkInfo(shopCompany);
        // 通联开启后，平台更新商家的工商信息也需要通过通联审核
        // 且只有平台开店审核失败的店铺才能更改工商信息，所以这里只需要设置企业信息，同步返回
        ShopCompanyVO shopCompanyVO = getShopCompanyByShopIdAndStatus(shopId, AuditStatus.SUCCESSAUDIT.value());
        if (Objects.nonNull(shopCompanyVO)) {
            throw new YamiShopBindException("工商信息已通过，无需修改");
        }
        List<ShopBankCard> shopBankCardList = shopBankCardService.list(new LambdaQueryWrapper<ShopBankCard>().eq(ShopBankCard::getShopId, shopId).eq(ShopBankCard::getStatus, 1));
        if (CollUtil.isEmpty(shopBankCardList)) {
            throw new YamiShopBindException("店铺银行卡为空，请补充");
        }
        updateByShopId(shopCompany);
        // 更新开店为待审核状态，影印件才可以回调
        ShopAuditing shopAuditing = shopAuditingService.getOne(new LambdaQueryWrapper<ShopAuditing>().eq(ShopAuditing::getShopId, shopId));
        if (Objects.equals(shopAuditing.getStatus(), AuditStatus.FAILAUDIT.value())) {
            shopAuditing.setStatus(AuditStatus.WAITAUDIT.value());
            shopAuditing.setRemarks("平台提交申请");
            shopAuditingService.updateById(shopAuditing);
        }
        // 通联审核
        ShopBankCard shopBankCardVO = shopBankCardList.get(0);
        AllinpayShopBankCardDTO allinpayShopBankCardDTO = new AllinpayShopBankCardDTO();
        allinpayShopBankCardDTO.setAccountNo(shopBankCardVO.getCardNo());
        allinpayShopBankCardDTO.setParentBankName(shopBankCardVO.getBankName());
        allinpayShopBankCardDTO.setBankName(shopBankCardVO.getBankName());
        allinpayShopBankCardDTO.setUnionBank(shopBankCardVO.getUnionBank());
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        shopBankCardService.allinpaySetCompanyInfo(allinpayShopBankCardDTO, shopId, shopCompany, shopDetail);
    }

    @Override
    public String idCardCollect(ShopCompanyVO shopCompany, Long shopId) {
        // 该方法会上传营业执照和身份证
        String businessLicense = getImgUrl(shopCompany.getBusinessLicense(), PicType.BUSINESS_LICENSE.getCode());
        if (!businessLicense.contains(HTTP)) {
            logger.info("店铺营业执照获取文件路径失败，原因{}", businessLicense);
            return businessLicense;
        }
        IdCardCollectByFileUploadResp businessResult = allinpayCompanyService.idCardCollectByFileUpload(null,
                null, PicType.BUSINESS_LICENSE.getCode(), businessLicense, AllinpayConstant.SHOP + shopId);
        if (Objects.equals(businessResult.getResult(), ID_CARD_FAIL_RESULT)) {
            return "店铺审核通过，影印件-营业执照上传失败，原因为：" + businessResult.getFailReason();
        }
        // 人面像
        String legalPicFaceToken = getImgUrl(shopCompany.getIdentityCardFront(), PicType.FRONT_OF_ID_CARD.getCode());
        if (!legalPicFaceToken.contains(HTTP)) {
            logger.info("店铺身份证-人面像获取文件路径失败，原因{}", legalPicFaceToken);
            return legalPicFaceToken;
        }
        // 国徽面
        String legalPicEmblemToken = getImgUrl(shopCompany.getIdentityCardLater(), PicType.REVERSE_SIDE_OF_ID_CARD.getCode());
        if (!legalPicEmblemToken.contains(HTTP)) {
            logger.info("店铺身份证-国徽像获取文件路径失败，原因{}", legalPicEmblemToken);
            return legalPicEmblemToken;
        }
        IdCardCollectByFileUploadResp idCardResult = allinpayCompanyService.idCardCollectByFileUpload(legalPicFaceToken,
                legalPicEmblemToken, null, null, AllinpayConstant.SHOP + shopId);
        if (Objects.equals(idCardResult.getResult(), ID_CARD_FAIL_RESULT)) {
            return "店铺审核通过，影印件上传失败，原因为：" + idCardResult.getFailReason();
        }
        // 所有都上传成功，改变店铺影印件状态
        shopDetailMapper.updateAllinpayIdCardStatus(shopId, IdCardCollectProcessStatus.WAIT_AUDIT.value());
        return AllinpayConstant.ALLINPAY_AUDIT_SUCCESS;
    }

    private String getImgUrl(String imageUrl, Integer picType) {
        if (Objects.isNull(imageUrl)) {
            return "店铺审核通过，" + PicType.getPicTypeName(picType) + "为空，请重新上传";
        }
        String fileType = attachFileService.getfileTypeByfilePath(imageUrl);
        if (Objects.isNull(fileType)) {
            return "店铺审核通过，" + PicType.getPicTypeName(picType) + "该图片类型为空";
        }
        String imgDomain = shopConfig.getUploadFile().resourceUrl();
        if (!imageUrl.contains(HTTP)) {
            // 给imageUrl 加上文件全路径
            if (Objects.isNull(imgDomain)) {
                // 未配置文件域名，无法上传成功图片
                return "店铺审核通过，" + "未配置文件域名，无法上传成功图片";
            }
            imageUrl = StringUtils.join(imgDomain, "/", imageUrl);
        }
        return imageUrl;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String uploadIdCard(ShopCompany shopCompany, ShopDetail shopDetailVO, Integer status) {
        Long shopId = shopDetailVO.getShopId();
        if (!Objects.equals(shopDetailVO.getIdCardCollectProcessStatus(), status)) {
            // 状态不同先更新状态
            shopDetailService.updateAllinpayIdCardStatus(AllinpayConstant.SHOP + shopId, status);
            shopDetailVO.setIdCardCollectProcessStatus(status);
        }
        if (Objects.equals(shopDetailVO.getIdCardCollectProcessStatus(), IdCardCollectProcessStatus.ALL.value())) {
            return "影印件已审核通过，请刷新页面";
        }
        if (Objects.equals(shopDetailVO.getIdCardCollectProcessStatus(), IdCardCollectProcessStatus.WAIT_AUDIT.value())) {
            return "影印件待审核中，请刷新影印件";
        }
        if (Objects.equals(shopDetailVO.getIdCardCollectProcessStatus(), IdCardCollectProcessStatus.UN_COMMITTED.value())) {
            logger.info("店铺{}影印件上传失败，尝试重新上传", shopId);
            // 还没提交上传
            ShopCompanyVO shopCompanyVO = BeanUtil.map(shopCompany, ShopCompanyVO.class);
            String result = idCardCollect(shopCompanyVO, shopId);
            if (Objects.equals(result, AllinpayConstant.ALLINPAY_AUDIT_SUCCESS)) {
                shopCompanyMapper.updateIdCardById(shopCompanyVO);
            }
            return result;
        }
        if (Objects.equals(shopDetailVO.getIdCardCollectProcessStatus(), IdCardCollectProcessStatus.REG.value())) {
            logger.info("店铺{}影印件只有工商信息审核通过了,尝试重新上传身份证信息", shopId);
            // 只有工商信息审核通过了,重新提交下身份证信息
            // 国徽面
            String legalPicEmblemToken = getImgUrl(shopCompany.getIdentityCardLater(), PicType.REVERSE_SIDE_OF_ID_CARD.getCode());
            if (!legalPicEmblemToken.contains(HTTP)) {
                logger.info("店铺身份证-国徽像获取文件路径失败，原因{}", legalPicEmblemToken);
                return legalPicEmblemToken;
            }
            // 人面像
            String legalPicFaceToken = getImgUrl(shopCompany.getIdentityCardFront(), PicType.FRONT_OF_ID_CARD.getCode());
            if (!legalPicFaceToken.contains(HTTP)) {
                logger.info("店铺身份证-人面像获取文件路径失败，原因{}", legalPicFaceToken);
                return legalPicFaceToken;
            }
            IdCardCollectByFileUploadResp fileUpload = allinpayCompanyService.idCardCollectByFileUpload(legalPicFaceToken,
                    legalPicEmblemToken, null, null, AllinpayConstant.SHOP + shopId);
            if (Objects.equals(fileUpload.getResult(), ID_CARD_FAIL_RESULT)) {
                return "店铺审核通过，影印件-身份证信息上传失败，原因为：" + fileUpload.getFailReason();
            }
            shopCompanyMapper.updateIdCardById(BeanUtil.map(shopCompany, ShopCompanyVO.class));
        }
        if (Objects.equals(shopDetailVO.getIdCardCollectProcessStatus(), IdCardCollectProcessStatus.ID_CARD.value())) {
            logger.info("店铺{}影印件只有法人信息通过,尝试重新上传工商信息", shopId);
            // 只有法人信息通过,重新提交下工商信息
            String businessLicense = getImgUrl(shopCompany.getBusinessLicense(), PicType.BUSINESS_LICENSE.getCode());
            if (!businessLicense.contains(HTTP)) {
                logger.info("店铺营业执照重新上传获取文件路径失败，原因{}", businessLicense);
                return businessLicense;
            }
            IdCardCollectByFileUploadResp fileUpload = allinpayCompanyService.idCardCollectByFileUpload(null,
                    null, PicType.BUSINESS_LICENSE.getCode(), businessLicense, AllinpayConstant.SHOP + shopId);
            if (Objects.equals(fileUpload.getResult(), ID_CARD_FAIL_RESULT)) {
                return "店铺审核通过，影印件-营业执照信息上传失败，原因为：" + fileUpload.getFailReason();
            }
            shopCompanyMapper.updateIdCardById(BeanUtil.map(shopCompany, ShopCompanyVO.class));
        }
        return "影印件更新成功";
    }

    @Override
    public void updateStatusToWaitAudit() {
        shopCompanyMapper.updateStatusToWaitAudit();
    }

    @Override
    public ShopCompanyVO getShopCompanyByShopIdAndStatus(Long shopId, Integer status) {
        ShopCompanyVO shopCompanyVO = shopCompanyMapper.getShopCompanyByShopIdAndStatus(shopId, status);
        // 检查工商信息是否有更新记录,若存在更新记录则发请求 查询审核信息 (逻辑上或许可以修改为存在多条工商信息记录)
        if (Objects.nonNull(shopCompanyVO)) {
            Integer recordStatus = shopCompanyMapper.getLatestRecord(shopId);
            if (!Objects.equals(AuditStatus.SUCCESSAUDIT.value(), recordStatus)) {
                shopCompanyVO.setEdit(true);
                shopCompanyVO.setNewStatus(recordStatus);
            }
        }
        return shopCompanyVO;
    }

    /**
     * 校验店铺工商信息
     *
     * @param shopCompany
     */
    private void checkInfo(ShopCompany shopCompany) {
        if (checkCreditCode(shopCompany.getCreditCode(), shopCompany.getShopId())) {
            throw new YamiShopBindException("yami.shop.company.credit.code.repeat");
        }
//        if (Objects.isNull(shopCompany.getStartTime())) {
//            throw new YamiShopBindException("yami.shop.company.date.not.empty");
//        }
        if (Objects.nonNull(shopCompany.getStartTime()) && Objects.nonNull(shopCompany.getEndTime()) && !shopCompany.getStartTime().before(shopCompany.getEndTime())) {
            throw new YamiShopBindException("yami.shop.business.date.error");
        }
        if (!allinpayCompanyService.getIsAllinpay()) {
            long count = shopAuditingMapper.selectCount(Wrappers.lambdaQuery(ShopAuditing.class)
                    .eq(ShopAuditing::getShopId, shopCompany.getShopId())
                    .eq(ShopAuditing::getStatus, 0)
            );
            if (count != 0) {
                throw new YamiShopBindException("yami.product.shop.AUDIT");
            }
        }
    }

    @Override
    public Boolean checkCreditCode(String creditCode, Long shopId) {
        List<Long> shopIds = shopCompanyMapper.getShopIdByCreditCode(creditCode);
        if (CollUtil.isNotEmpty(shopIds)) {
            boolean isSame = true;
            for (Long creditShopId : shopIds) {
                if (!Objects.equals(creditShopId, shopId)) {
                    isSame = false;
                    break;
                }
            }
            return !isSame;
        }
        return false;
    }
}
